package metrics

import (
	"io"
	"math"
	"time"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/ethereum/go-ethereum/log"

	"github.com/ethereum-optimism/optimism/op-batcher/config"
	"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
	"github.com/ethereum-optimism/optimism/op-service/eth"
	opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
	txmetrics "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
)

type noopMetrics struct {
	opmetrics.NoopRefMetrics
	txmetrics.NoopTxMetrics
	opmetrics.NoopRPCMetrics
}

var NoopMetrics Metricer = new(noopMetrics)

func (*noopMetrics) Document() []opmetrics.DocumentedMetric { return nil }

func (*noopMetrics) RecordInfo(version string) {}
func (*noopMetrics) RecordUp()                 {}

func (*noopMetrics) RecordLatestL1Block(l1ref eth.L1BlockRef)               {}
func (*noopMetrics) RecordL2BlocksLoaded(eth.L2BlockRef)                    {}
func (*noopMetrics) RecordChannelOpened(derive.ChannelID, int)              {}
func (*noopMetrics) RecordL2BlocksAdded(eth.L2BlockRef, int, int, int, int) {}
func (*noopMetrics) RecordL2BlockInPendingQueue(uint64, uint64)             {}
func (*noopMetrics) RecordL2BlockInChannel(uint64, uint64)                  {}
func (*noopMetrics) RecordPendingBlockPruned(uint64, uint64)                {}

func (*noopMetrics) RecordChannelClosed(derive.ChannelID, int, int, int, int, error) {}

func (*noopMetrics) RecordChannelFullySubmitted(derive.ChannelID) {}
func (*noopMetrics) RecordChannelTimedOut(derive.ChannelID)       {}
func (*noopMetrics) RecordChannelQueueLength(int)                 {}

func (*noopMetrics) RecordThrottleIntensity(intensity float64, controllerType config.ThrottleControllerType) {
}
func (*noopMetrics) RecordThrottleParams(maxTxSize, maxBlockSize uint64)                       {}
func (*noopMetrics) RecordThrottleControllerType(controllerType config.ThrottleControllerType) {}
func (*noopMetrics) RecordUnsafeBytesVsThreshold(pendingBytes, threshold uint64, controllerType config.ThrottleControllerType) {
}

func (*noopMetrics) RecordUnsafeDABytes(int64) {}

// PID Controller specific metrics
func (*noopMetrics) RecordThrottleControllerState(error, integral, derivative float64) {}
func (*noopMetrics) RecordThrottleResponseTime(duration time.Duration)                 {}

func (*noopMetrics) RecordBatchTxSubmitted() {}
func (*noopMetrics) RecordBatchTxSuccess()   {}
func (*noopMetrics) RecordBatchTxFailed()    {}
func (*noopMetrics) RecordBlobUsedBytes(int) {}
func (*noopMetrics) StartBalanceMetrics(log.Logger, *ethclient.Client, common.Address) io.Closer {
	return nil
}
func (nm *noopMetrics) PendingDABytes() float64 {
	return 0.0
}

// ThrottlingMetrics is a noopMetrics that always returns a max value for PendingDABytes, to use in testing batcher
// backlog throttling.
type ThrottlingMetrics struct {
	noopMetrics
}

func (nm *ThrottlingMetrics) PendingDABytes() float64 {
	return math.MaxFloat64
}

func (*noopMetrics) ClearAllStateMetrics() {}
